/*
 * File:   OddSquare.h
 * Author: jcrada
 *
 * Created on 28 April 2011, 12:03 PM
 */

#ifndef ECB_ODDSQUARE_H
#define	ECB_ODDSQUARE_H

#include "ecb/base/Problem.h"
#include <cmath>

namespace ecb {

    /* Source:
     * @incollection{springer-dif.evo,
         Author = {Price, Kenneth and Storn, Rainer M. and Lampinen, Jouni A.},
         title={{Appendix}},
         booktitle = {Differential Evolution: A Practical Approach to Global Optimization},
         series={Natural Computing Series},
         editor={Rozenberg, G. and Bäck, Th. and Eiben, A. E. and Kok, J. N. and Spaink, H. P.},
         publisher = {Springer-Verlag Berlin Heidelberg},
         pages = {513-533},
         year = {2005}
         }
     */
    class OddSquare : public Problem {
    protected:

        void distanceToCenter(const std::vector<scalar>& x,
                scalar& euclidean, scalar& h) {
            static const scalar CENTER[10] = {1, 1.3, 0.8, -0.4, -1.3, 1.6, -0.2, -0.6, 0.5, 1.4};
            scalar max = -std::numeric_limits<scalar>::infinity();
            euclidean = 0;
            for (size_t i = 0; i < x.size(); ++i) {
                scalar diff = x[i] - CENTER[i % 10];
                euclidean += diff * diff;

                if (max < fabs(diff)) max = fabs(diff);
            }

            euclidean = sqrt(euclidean);
            //      h = sqrt(x.size() * max * max); //according to code...
            h = x.size() * max * max; //according to reference
        }

    public:

        OddSquare(const std::string& id = "OddSquare", const std::string& name = "OddSquare",
                int dimensions = 0, scalar minimum = -5 * M_PI, scalar maximum = 5 * M_PI,
                bool minimization = true) :
        Problem(id, name, dimensions, minimum, maximum, minimization) { }

        scalar f(const std::vector<scalar>& x) {
            scalar d, h;
            distanceToCenter(x, d, h);
            return -std::exp(-d / (2 * M_PI)) * std::cos(M_PI * d) * (1 + (0.02 * h) / (d + 0.01));
        }
    };
}

#endif	/* ECB_ODDSQUARE_H */

